package com.hksj.Intelligentmanagement.mqtt.corn;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hksj.Intelligentmanagement.dto.CreateOrderDTO;
import com.hksj.Intelligentmanagement.entity.CallTaskOrderEntity;
import com.hksj.Intelligentmanagement.entity.CallUserEntity;
import com.hksj.Intelligentmanagement.enums.QosEnum;
import com.hksj.Intelligentmanagement.mqtt.client.IMqttClient;
import com.hksj.Intelligentmanagement.mqtt.command.*;
import com.hksj.Intelligentmanagement.mqtt.constant.Constant;
import com.hksj.Intelligentmanagement.service.CallTaskOrderService;
import com.hksj.Intelligentmanagement.service.CallUserService;
import com.hksj.Intelligentmanagement.utils.RedisCache;
import com.hksj.Intelligentmanagement.utils.UnicodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class ConnStateJob {
    @Autowired(required = false)
    private IMqttClient mqttClient;

    @Autowired
    private RedisCache<String> strCache;

    @Autowired
    private RedisCache<Set<WatchInfoDTO>> watchInfoCache;

    @Autowired
    private CallTaskOrderService taskOrderService;

    @Autowired
    private CallUserService callUserService;

    @Scheduled(cron = "0/10 * * * * ?")
    public void getConnState(){
        if (!ObjectUtils.isEmpty(mqttClient)){
            Msg<ConnStateMsgData> msg = new Msg<>();
            ConnStateMsgData connStateMsgData = new ConnStateMsgData();
            msg.setData(connStateMsgData);
            mqttClient.publish(JSON.toJSONString(msg), CommandConstant.TOPIC_SEND_DATA);
        }
    }

    /**
     * 下发清洁任务单
     */
    @Scheduled(cron = "0/15 * * * * ?")
    public void sendTaskOrder(){
        Object flag = strCache.getCacheObject(CommandConstant.TASK_ORDER_NEED_TO_OBTAIN_FLAG_1);
        if (ObjectUtils.isEmpty(flag)){

            CallTaskOrderEntity taskOrder = taskOrderService.lambdaQuery()
                    .eq(CallTaskOrderEntity::getState, 1)
                    .eq(CallTaskOrderEntity::getType,1)
                    .orderByAsc(CallTaskOrderEntity::getCreateAt)
                    .last("limit 1")
                    .one();

            if (!ObjectUtils.isEmpty(taskOrder)){
                //将任务单发布标识存入缓存 抢单成功后删除标识  停止抢单
                strCache.setCacheObject(Constant.TO_OBTAIN_ORDER + taskOrder.getOrderNo(), DateUtil.formatDateTime(new Date()));

                //发布消息
                CreateOrderDTO createOrderDTO = new CreateOrderDTO();
                createOrderDTO.setOrderNo(taskOrder.getOrderNo());
                createOrderDTO.setAddress(taskOrder.getAddress());
                createOrderDTO.setOperatingRoomNo(taskOrder.getOperatingRoomNo());
                sendTaskOrder(createOrderDTO,1);
            }
        }
    }

    /**
     * 下发转运任务单
     */
//    @Scheduled(cron = "0/18 * * * * ?")
    public void sendTaskOrder2(){
        Object flag = strCache.getCacheObject(CommandConstant.TASK_ORDER_NEED_TO_OBTAIN_FLAG_2);
        if (ObjectUtils.isEmpty(flag)){

            CallTaskOrderEntity taskOrder = taskOrderService.lambdaQuery()
                    .eq(CallTaskOrderEntity::getState, 1)
                    .eq(CallTaskOrderEntity::getType,2)
                    .orderByAsc(CallTaskOrderEntity::getCreateAt)
                    .last("limit 1")
                    .one();

            if (!ObjectUtils.isEmpty(taskOrder)){
                //将任务单发布标识存入缓存 抢单成功后删除标识  停止抢单
                strCache.setCacheObject(Constant.TO_OBTAIN_ORDER + taskOrder.getOrderNo(),DateUtil.formatDateTime(new Date()));

                //发布消息
                CreateOrderDTO createOrderDTO = new CreateOrderDTO();
                createOrderDTO.setOrderNo(taskOrder.getOrderNo());
                createOrderDTO.setAddress(taskOrder.getAddress());
                createOrderDTO.setOperatingRoomNo(taskOrder.getOperatingRoomNo());
                sendTaskOrder(createOrderDTO,2);
            }
        }
    }

    public void sendTaskOrder(CreateOrderDTO createOrderDTO,Integer type){
        Set<WatchInfoDTO> watchInfos = watchInfoCache.getCacheObject(CommandConstant.CACHE_LOGIN_WATCH_INFO);

        if (!ObjectUtils.isEmpty(watchInfos)){
            //手环分组
            List<CallUserEntity> users = callUserService
                    .lambdaQuery()
                    .eq(CallUserEntity::getTypeId, type)
                    .in(CallUserEntity::getMac, watchInfos.stream().map(itme -> itme.getAddr()).collect(Collectors.toList()))
                    .list();
            watchInfos = watchInfos.stream()
                    .filter(item -> users.stream().map(u -> u.getMac()).collect(Collectors.toList()).contains(item.getAddr()))
                    .collect(Collectors.toSet());

            if (!ObjectUtils.isEmpty(watchInfos)){
                //设置全局任务待抢标识符
                if (type == 1){
                    strCache.setCacheObject(CommandConstant.TASK_ORDER_NEED_TO_OBTAIN_FLAG_1,"true",30, TimeUnit.MINUTES);
                }else if(type == 2){
                    strCache.setCacheObject(CommandConstant.TASK_ORDER_NEED_TO_OBTAIN_FLAG_2,"true",30, TimeUnit.MINUTES);
                }

                Msg<SendMsgData> msg = new Msg<>();
                SendMsgData sendMsgData = new SendMsgData();

                ArrayList<SendMsgData.DeviceInfo> deviceInfos = new ArrayList<>();
                for (WatchInfoDTO watchInfo : watchInfos) {
                    deviceInfos.add(sendMsgData.createDeviceInfo(watchInfo.getAddr()));
                }

                sendMsgData.setDevices_num(deviceInfos.size());
                sendMsgData.setDevices(deviceInfos);
                //发布任务 -address
                String address = createOrderDTO.getAddress();
                String addrLen = HexUtil.toHex(address.length() * 2 + 2);
                addrLen = addrLen.length() == 1 ? "0" + addrLen : addrLen;
                String raw = UnicodeUtils.toUnicode(address);
                StringBuffer sb = new StringBuffer();
                sb.append("A0040B00").append(addrLen).append(raw).append("FFFF");
                sendMsgData.setSend_infos(Arrays.asList(sendMsgData.createSendInfo(sb.toString())));
                msg.setData(sendMsgData);
                mqttClient.publish(JSONObject.toJSONString(msg),CommandConstant.TOPIC_SEND_DATA, QosEnum.Qos2,true);

                //发布任务 -operatingRoomNo
                String operatingRoomNo = createOrderDTO.getOperatingRoomNo();
                String operatingRoomNoLen = HexUtil.toHex(operatingRoomNo.length() * 2 + 2);
                operatingRoomNoLen = operatingRoomNoLen.length() == 1 ? "0" + operatingRoomNoLen : operatingRoomNoLen;
                raw = UnicodeUtils.toUnicode(operatingRoomNo);
                sb = new StringBuffer();
                sb.append("A0040B01").append(operatingRoomNoLen).append(raw).append("FFFF");
                sendMsgData.setSend_infos(Arrays.asList(sendMsgData.createSendInfo(sb.toString())));
                msg.setData(sendMsgData);
                mqttClient.publish(JSONObject.toJSONString(msg),CommandConstant.TOPIC_SEND_DATA, QosEnum.Qos2,true);

                //发布任务 -orderNo
                String orderNo = createOrderDTO.getOrderNo();
                String orderNoLen = HexUtil.toHex(orderNo.length() * 2 + 2);
                orderNoLen = orderNoLen.length() == 1 ? "0" + orderNoLen : orderNoLen;
                raw = UnicodeUtils.toUnicode(orderNo);
                sb = new StringBuffer();
                sb.append("A0040B02").append(orderNoLen).append(raw).append("FFFF");
                sendMsgData.setSend_infos(Arrays.asList(sendMsgData.createSendInfo(sb.toString())));
                msg.setData(sendMsgData);
                mqttClient.publish(JSONObject.toJSONString(msg),CommandConstant.TOPIC_SEND_DATA, QosEnum.Qos2,true);

                try{
                    Thread.sleep(2000);
                    //通知
                    sendMsgData.setSend_infos(Arrays.asList(sendMsgData.createSendInfo("A0040BFF02")));
                    mqttClient.publish(JSONObject.toJSONString(msg),CommandConstant.TOPIC_SEND_DATA);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }else{
            System.out.println("当前没有手环在线");
        }
    }

}
